#include "HAL_USP_Config.h"
#include "py32f4xx.h"
#include "typedef.h"

#define __CONNECT_A_B(A,B)  A##B
#define _CONNECT_RCC_PLL_MUL_X(X)   __CONNECT_A_B(RCC_PLL_MUL, X)
#define RCC_PLL_MUL_X _CONNECT_RCC_PLL_MUL_X(PLL_MUL)

#if (SYSCLK_SRC == 0)
    #define F_SYSCLK     HSI_VALUE
#elif (SYSCLK_SRC == 1)
    #define F_SYSCLK     HSE_VALUE
#elif (SYSCLK_SRC == 2)
    #define F_SYSCLK     (HSI_VALUE * PLL_MUL)
#elif (SYSCLK_SRC == 3)
    #define F_SYSCLK     (HSE_VALUE * PLL_MUL)
#else
    #error "SYSCLK_SRC define error."
#endif

#define F_HCLK      F_SYSCLK
#define F_APB1CLK   F_HCLK

#if (F_HCLK <= 28000000)
    #define FLASH_LATENCY_X     FLASH_LATENCY_0
#elif  (F_HCLK <= 60000000)
    #define FLASH_LATENCY_X     FLASH_LATENCY_1
#elif  (F_HCLK <= 90000000)
    #define FLASH_LATENCY_X     FLASH_LATENCY_3
#elif  (F_HCLK <= 120000000)
    #define FLASH_LATENCY_X     FLASH_LATENCY_4
#elif  (F_HCLK <= 144000000)
    #define FLASH_LATENCY_X     FLASH_LATENCY_5
#else
    #define FLASH_LATENCY_X     FLASH_LATENCY_6
#endif

#if (HSE_VALUE <= 8000000)
    #define HSE_FREQ_RANG   RCC_HSE_4_8MHz
#elif (HSE_VALUE <= 16000000)
    #define HSE_FREQ_RANG   RCC_HSE_8_16MHz
#else//#elif (HSE_VALUE <= 32000000)
    #define HSE_FREQ_RANG   RCC_HSE_16_32MHz
#endif




void EnablePeriphClk(void)
{
    __IO uint32_t tmpreg; 

    RCC->AHB1ENR = RCC_AHB1_PERIPH_CLKEN;
    RCC->AHB2ENR = RCC_AHB2_PERIPH_CLKEN;
    RCC->APB1ENR = RCC_APB1_PERIPH_CLKEN;
    RCC->APB2ENR = RCC_APB2_PERIPH_CLKEN;
    /* Delay after an RCC peripheral clock enabling */
    tmpreg = READ_BIT(RCC->APB2ENR, RCC_APB2ENR_ADC1EN);
    UNUSED(tmpreg); 
}

#if (SYSCLK_SRC == 0)
FORCE_IN_LINE void SystemClock_Config(void){}
#else

void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
#if (SYSCLK_SRC == 0)
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
#elif (SYSCLK_SRC == 1)
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_LSI;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEFreq = HSE_FREQ_RANG;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
#elif (SYSCLK_SRC == 2)
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL_X;
#elif (SYSCLK_SRC == 3)
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_LSI;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.HSEFreq = HSE_FREQ_RANG;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL_X;
#else
    #error "SYSCLK_SRC define error."
#endif
    RCC_OscInitStruct.LSIState = RCC_LSI_ON;
#if LSE_EN
    RCC_OscInitStruct.OscillatorType |= RCC_OSCILLATORTYPE_LSE
    RCC_OscInitStruct.LSEState = RCC_LSE_ON;
    RCC_OscInitStruct.LSEDriver = RCC_LSEDRIVE_HIGH;
#endif
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        while(1);
    }

    /** Initializes the CPU, AHB and APB buses clocks
     */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
#if (SYSCLK_SRC == 0)
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
#elif (SYSCLK_SRC == 1)
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
#else
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
#endif
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;  // HCLK = SYSCLK
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;   // APB1CLK = HCLK
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;   // APB2CLK = HCLK
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_X) != HAL_OK)// SystemCoreClock 将会被更新
    {
        while(1);
    }
}
#endif
